package com.wind.httpProxyServer.threads;

import java.io.*;
import java.net.Socket;
import java.net.SocketException;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;

import com.wind.httpProxyServer.bean.ProcessConfigBean;
import com.wind.httpProxyServer.constants.Properties;
import com.wind.httpProxyServer.constants.RequestMethod;
import com.wind.httpProxyServer.httpMessage.HttpRequestMessage;
import com.wind.httpProxyServer.httpMessage.exception.BuildHttpMessageError;
import com.wind.httpProxyServer.httpMessage.exception.ConnectServerError;
import com.wind.httpProxyServer.manager.WhiteListManager;
import com.wind.httpProxyServer.proxy.Proxy;
import com.wind.httpProxyServer.proxy.ServerProxy;
import com.wind.httpProxyServer.utils.SocketUtil;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.wind.httpProxyServer.httpMessage.startLine.RequestStartLine;

/**
 * Http代理线程
 *
 * @author qq
 */
public class ServerHttpProxyThread extends Thread {
    private final static Logger log = LoggerFactory.getLogger(ServerHttpProxyThread.class);

    /*
     * 客户端相关
     */
    /**
     * 客户端Socket
     */
    private Socket clientSocket;

    /**
     * 客户端输入流
     */
    private InputStream clientInputStream;



    /*
     * 服务端相关
     */
    /**
     * 服务端Socket
     */
    private Socket serverSocket;

    private ProcessConfigBean processConfigBean;
    /*
     * constructor
     */
    private ServerHttpProxyThread() {
    }

    public ServerHttpProxyThread(Socket clientSocket,ProcessConfigBean processConfigBean) {
        //super();
        this.clientSocket = clientSocket;
        this.processConfigBean =processConfigBean;
        try {
            this.clientInputStream = clientSocket.getInputStream();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        /*
         * 解析客户端请求
         */
        HttpRequestMessage requestMessage = null;
        try {
            requestMessage = new HttpRequestMessage(clientInputStream);
        } catch (BuildHttpMessageError e1) {
            e1.printStackTrace();

            SocketUtil.closeSocket(clientSocket);
            return;
        }


        //是否在白名单里面
        boolean whiteListflag =validateIsWhite();

       // 如果不在ip白名单里面,需要身份身份验证

        if(!whiteListflag) {
            Map<String, String> headers = requestMessage.getHeaders();
            String proxHeader = "proxy-authorization";
            boolean flag = headers.containsKey(proxHeader);
            PrintWriter out = null;
            try {
                out = new PrintWriter(new OutputStreamWriter(clientSocket.getOutputStream()), true);
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (!flag) {
                out.println("HTTP/1.1 407 Proxy Authentication Required");
                out.println("Proxy-Authenticate: Basic realm=\"Proxy Login\"");
                out.println();
                out.flush();
                return;
            } else {
                String basicString = headers.get(proxHeader);
                String authString = new String(Base64.getDecoder().decode(basicString.substring(6).trim()));
                String[] authParts = authString.split(":");
                if (authParts.length == 2) {
                    String username = authParts[0];
                    String password = authParts[1];
                    if (validateUser(username, password)) {
                        // 身份验证成功，将用户名和密码存入 authMap 中，以便后续使用
                        String auth0 = Base64.getEncoder().encodeToString(authString.getBytes());
                        System.out.println(auth0);
                        System.out.println("身份验证成功");

                    } else {
                        out.println("HTTP/1.1 401 Unauthorized");
                        out.println("Content-Length: 0");
                        out.println();
                        out.flush();
                        return;
                    }
                }

            }
        }else{

        }

        //requestMessage = (HttpRequestMessage) requestMessage.decryptHttpMessage(); // 解密

        // 请求方法
        RequestMethod httpRequestMethod = ((RequestStartLine) requestMessage.getStartLine()).getMethod();
        System.out.println("httpRequestMethod.name():"+httpRequestMethod.name());
        System.out.println("[原始请求:]");
        System.out.print(requestMessage);
        System.out.println("----------");

        /*
         * 连接服务器
         */
        String hostHeader = requestMessage.getHeader("host"); // 如果没有Host首部，则从Url中解析
        String host = hostHeader;
        int port = 80; // 默认端口
        if (hostHeader.contains(":")) {
            String[] hostArr = hostHeader.split(":");
            host = hostArr[0];
            port = Integer.parseInt(hostArr[1]);
        }
        if (RequestMethod.CONNECT == httpRequestMethod) { // https
            port = 443;
        }

        /*
         *
         */
        try {
            if (RequestMethod.CONNECT != httpRequestMethod) {
                this.serverSocket = SocketUtil.connectServer(host, port, Properties.ServerConnectTimeout);
            }else{
                this.serverSocket = SocketUtil.connectServer(host, port, Properties.ServerConnectTimeout);
              //  this.serverSocket = SocketUtil.connectServerHttps(host, port, Properties.ServerConnectTimeout);
            }

        } catch (ConnectServerError e) {
           // e.printStackTrace();

            SocketUtil.closeSocket(clientSocket, serverSocket);
            return;
        }

        if (RequestMethod.CONNECT != httpRequestMethod) { // 代理http
            try {
               // this.clientSocket.setSoTimeout(Properties.ClientSoceketReadTimeout); // 设置读取浏览器Socket超时时间
                this.serverSocket.setSoTimeout(Properties.ServerSocketReadTimeout); // 设置读取代理服务器Socket超时时间
            } catch (SocketException e) {
                //e.printStackTrace();
            }
        }

        /*
         * 转发流量
         */
        Proxy proxy = new ServerProxy(clientSocket, serverSocket, requestMessage);
        proxy.proxy();
    }


    private boolean validateUser(String username, String password) {
        return username.equals(processConfigBean.getUsername())&&password.equals(processConfigBean.getPassword());
    }


    private boolean validateIsWhite() {

        String clientIP = clientSocket.getInetAddress().getHostAddress();

        if(clientIP.equals("127.0.0.1")){
            return true;
        }
        System.out.println("clientIP:"+clientIP);
        CopyOnWriteArrayList<String> columnWhites = WhiteListManager.columnWhites;
        if(CollectionUtils.isNotEmpty(columnWhites)) {
            for (String columnWhite : columnWhites) {
                boolean pass = WhiteListManager.pass(clientIP, columnWhite);
               System.out.println("123"+clientIP+columnWhite+ " "+pass);
                if (pass) {
                    return true;
                }
            }
        }

        if(WhiteListManager.whites.containsKey(processConfigBean.getId())){
            List<String> ips = WhiteListManager.whites.get(processConfigBean.getId());
            if(CollectionUtils.isNotEmpty(ips)) {
                for (String ip : ips) {
                    boolean pass = WhiteListManager.pass(clientIP, ip);
                    if (pass) {
                        return true;
                    }
                }
            }
        }
        return false;
    }



}
